#include "VolumeObject.h"
#include "OCMain/ZipUtil.h"

namespace OCPP{namespace Volume
{
	CVolumeObject::CVolumeObject()
	{

	}
	CVolumeObject::~CVolumeObject()
	{

	}

	void CVolumeObject::setUint8Image(std::shared_ptr<Image> image)
	{
		mUint8Image = image;
	}

	void CVolumeObject::writeToStream(std::ostream& os)
	{
		String mFeatureJSON = mVolumeMeta.toString();

		w3dmheader header;
		header.magic[0] = 'w', header.magic[1] = '3', header.magic[2] = 'd', header.magic[3] = 'm';
		header.version = 1;

		//json
		header.featureTableJSONByteLength = mFeatureJSON.length();
		os.write((const char*)&header, sizeof(header));
		os.write(mFeatureJSON.c_str(), header.featureTableJSONByteLength);
		if (os.fail())
		{
			return;
		}

		Image& image = *mUint8Image.get();

		std::stringstream sstream;
		size_t writeBeforeSize = os.tellp();

		sstream.write((const char*)image.getData(), image.getSize());

		bool ret = ZipUtil::compress(os, sstream.str());

		if (!ret)
		{
			return;
		}

		header.featureTableBinaryByteLength = os.tellp();
		header.featureTableBinaryByteLength -= writeBeforeSize;
		header.byteLength =
			sizeof(w3dmheader) +
			header.featureTableJSONByteLength +
			header.featureTableBinaryByteLength;

		os.seekp(std::ios::beg);
		os.write((const char*)&header, sizeof(header));
		os.seekp(std::ios::end);
	}

	void CVolumeObject::writeToW3DM(String filename)
	{
		std::ofstream ofs(filename.c_str(), std::ios::binary);
		if (ofs)
		{
			writeToStream(ofs);
			ofs.close();
		}
	}

	std::shared_ptr<Image> CVolumeObject::_CreateVolumeImage(int s, int t, int r, PixelFormat pixelFormat)
	{
		std::shared_ptr<Image> image = std::make_shared<Image>(pixelFormat,s,t,r);
		memset(image->getData(),0, image->getSize());
		return image;
	}

#define EARTH_RADIUS 6378137.f

	float CVolumeObject::width_in_meter(float lat_in_degree, float width_in_degree)
	{
		return cos(Math::AngleUnitsToRadians(lat_in_degree)) * EARTH_RADIUS * Math::PI * (width_in_degree / 180.0);
	}

	float CVolumeObject::height_in_meter(float height_in_degree)
	{
		return EARTH_RADIUS * Math::PI * (height_in_degree / 180.0);
	}
}}